package model

import (
	"fmt"
	"strings"
	"time"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/consts"
	"yunj/pkg/yunj/app/enum/admin/authenum"
	"yunj/pkg/yunj/app/enum/admin/departmentenum"
	"yunj/pkg/yunj/app/enum/stateenum"
	"yunj/pkg/yunj/util"
)

type AdminMember struct {
	Id                          uint64              `gorm:"primary_key;autoIncrement;column:id" json:"id,omitempty" form:"id"`
	Pid                         uint64              `gorm:"column:pid" json:"pid" form:"pid"`
	Username                    string              `gorm:"column:username;uniqueIndex" json:"username" form:"username"`
	PasswordSalt                string              `gorm:"column:password_salt" json:"password_salt" form:"password_salt"`
	PasswordHash                string              `gorm:"column:password_hash" json:"password_hash" form:"password_hash"`
	Name                        string              `gorm:"column:name;index:idx_name" json:"name" form:"name"`
	LastLoginIp                 string              `gorm:"column:last_login_ip" json:"last_login_ip" form:"last_login_ip"`
	LastLoginAt                 *time.Time          `gorm:"column:last_login_at" json:"last_login_at,omitempty" form:"last_login_at"`
	CreatedAt                   *time.Time          `gorm:"column:created_at" json:"created_at,omitempty" form:"created_at"`
	UpdatedAt                   *time.Time          `gorm:"column:updated_at" json:"updated_at,omitempty" form:"updated_at"`
	State                       uint8               `gorm:"column:state" json:"state" form:"state"`
	Roles                       []*AdminRole        `gorm:"many2many:admin_member_role;joinForeignKey:member_id;joinReferences:role_id"`
	isHasAllAuthSet             bool                // 是否拥有全部权限属性是否设置
	isHasAllAuth                bool                // 是否拥有全部权限
	ownRoles                    []*AdminRole        // 拥有的角色（状态正常）
	ownRoleAuthKeyMap           map[string]struct{} // 拥有的角色（状态正常）权限key的map
	OwnAuthKeyMap               map[string]struct{} `gorm:"-"` // 拥有的权限key的map
	OwnAuths                    []*AdminAuth        `gorm:"-"` // 拥有的权限
	OwnSidebarMenuAuths         []*AdminAuth        `gorm:"-"` // 拥有的侧边栏菜单权限
	OwnTopMenuAuths             []*AdminAuth        `gorm:"-"` // 拥有的顶部菜单权限
	managerDepartmentIds        []uint64            `gorm:"-"` // 管理的部门ids（作为负责人）
	viewAndOperateDepartmentIds []uint64            `gorm:"-"` // 可查看和操作的部门ids（作为负责人，包含自己部门和下级部门）
	viewAndOperateMemberIds     []uint64            `gorm:"-"` // 可查看和操作的成员ids（包含自己，作为负责人，包含自己部门和下级部门所有成员）
}

// 判断当前成员是否拥有全部权限
func (m *AdminMember) IsHasAllAuth() bool {
	if m.isHasAllAuthSet {
		return m.isHasAllAuth
	}
	isHasAllAuth := false
	if m.Pid == 0 {
		isHasAllAuth = true
	} else {
		for _, role := range m.Roles {
			if role.Code == consts.ADMINISTRATOR_ROLE_CODE {
				isHasAllAuth = true
				break
			}
		}
	}
	m.isHasAllAuthSet = true
	m.isHasAllAuth = isHasAllAuth
	return m.isHasAllAuth
}

// 获取拥有的角色
func (m *AdminMember) GetOwnRoles() []*AdminRole {
	if m.ownRoles != nil {
		return m.ownRoles
	}
	ownRoles := make([]*AdminRole, 0, len(m.Roles))
	for _, role := range m.Roles {
		if role.State == stateenum.NORMAL {
			ownRoles = append(ownRoles, role)
		}
	}
	m.ownRoles = ownRoles
	return m.ownRoles
}

// 获取拥有的角色（状态正常）权限key的map
func (m *AdminMember) GetOwnRoleAuthKeyMap() map[string]struct{} {
	if m.ownRoleAuthKeyMap != nil {
		return m.ownRoleAuthKeyMap
	}
	ownRoleAuthKeyMap := map[string]struct{}{}
	roles := m.GetOwnRoles()
	for _, role := range roles {
		for _, authKey := range role.Auths {
			ownRoleAuthKeyMap[authKey] = struct{}{}
		}
	}
	m.ownRoleAuthKeyMap = ownRoleAuthKeyMap
	return m.ownRoleAuthKeyMap
}

// 判断当前成员是否是部门负责人
func (m *AdminMember) GetManagerDepartmentIds() (departmentIds []uint64, err error) {
	if m.managerDepartmentIds != nil {
		return m.managerDepartmentIds, nil
	}
	tablePrefix := global.Config.Database.TablePrefix
	err = global.MySQL.Table(tablePrefix+"admin_member_department_postion as amdp").
		Joins("inner join "+tablePrefix+"admin_department_postion adp on adp.id=amdp.department_postion_id"+" inner join "+tablePrefix+"admin_department ad on ad.id=adp.department_id").
		Where("amdp.member_id = ? and adp.type in ? and adp.state = ? and ad.state = ?", m.Id, []int{int(departmentenum.POSTION_TYPE_MAIN), int(departmentenum.POSTION_TYPE_SECONDARY)}, stateenum.NORMAL, stateenum.NORMAL).
		Pluck("ad.id", &departmentIds).Error
	if err != nil {
		global.Logger.Error(util.FormatError(err, fmt.Sprintf("获取成员%d的管理的部门ids异常！", m.Id)))
		err = fmt.Errorf("获取成员%d的管理的部门ids异常！%v", m.Id, err)
		return
	}
	m.managerDepartmentIds = departmentIds
	return
}

// 判断当前成员是否是部门负责人
func (m *AdminMember) IsDepartmentManager() (ok bool, err error) {
	departmentIds, err := m.GetManagerDepartmentIds()
	if err != nil {
		return
	}
	ok = len(departmentIds) > 0
	return
}

// 获取可查看和操作的部门ids（作为负责人，包含自己部门和下级部门）
func (m *AdminMember) GetViewAndOperateDepartmentIds() (departmentIds []uint64, err error) {
	if m.viewAndOperateDepartmentIds != nil {
		return m.viewAndOperateDepartmentIds, nil
	}
	departmentIds = []uint64{}
	// 判断负责部门ids
	managerDepartmentIds, err := m.GetManagerDepartmentIds()
	if err != nil {
		return
	}
	if len(managerDepartmentIds) > 0 {
		// 将负责部门ids放到可查看和操作的部门ids切片中
		departmentIds = append(departmentIds, managerDepartmentIds...)

		// pids匹配的json值组装
		managerDepartmentIdStrs := make([]string, 0, len(managerDepartmentIds))
		for _, id := range managerDepartmentIds {
			managerDepartmentIdStrs = append(managerDepartmentIdStrs, fmt.Sprintf("%d", id))
		}
		pidsJson := fmt.Sprintf("[%s]", strings.Join(managerDepartmentIdStrs, ","))

		// 获取负责部门的下级部门ids
		var managerSubDepartmentIds []uint64
		err = global.MySQL.Model(&AdminDepartment{}).
			Where("JSON_OVERLAPS(pids, ?) and state = ?", pidsJson, stateenum.NORMAL).
			Pluck("id", &managerSubDepartmentIds).Error
		if err != nil {
			global.Logger.Error(util.FormatError(err, fmt.Sprintf("获取成员%d负责部门的下级部门ids异常！", m.Id)))
			err = fmt.Errorf("获取成员%d负责部门的下级部门ids异常！%v", m.Id, err)
			return
		}
		// 将负责部门的下级部门ids放到可查看和操作的部门ids切片中
		departmentIds = append(departmentIds, managerSubDepartmentIds...)
	}
	m.viewAndOperateDepartmentIds = departmentIds
	return
}

// 获取可查看和操作的成员ids（包含自己，作为负责人，包含自己部门和下级部门所有成员）
func (m *AdminMember) GetViewAndOperateMemberIds() (memberIds []uint64, err error) {
	if m.viewAndOperateMemberIds != nil {
		return m.viewAndOperateMemberIds, nil
	}
	memberIds = []uint64{}
	// 获取可查看和操作的部门ids
	viewAndOperateDepartmentIds, err := m.GetViewAndOperateDepartmentIds()
	if err != nil {
		return
	}
	if len(viewAndOperateDepartmentIds) > 0 {
		// 查询可查看和操作的部门下所有成员ids
		var departmentMemberIds []uint64
		tablePrefix := global.Config.Database.TablePrefix
		err = global.MySQL.Table(tablePrefix+"admin_member_department as amd").
			Joins("inner join "+tablePrefix+"admin_member am on am.id=amd.member_id").
			Where("amd.department_id in ? and am.state = ?", viewAndOperateDepartmentIds, stateenum.NORMAL).
			Pluck("am.id", &departmentMemberIds).Error
		if err != nil {
			global.Logger.WithField("viewAndOperateDepartmentIds", viewAndOperateDepartmentIds).Error(util.FormatError(err, fmt.Sprintf("查询可查看和操作的部门下所有成员ids异常！")))
			err = fmt.Errorf(" 查询可查看和操作的部门下所有成员ids！%v", err)
			return
		}
		memberIds = append(memberIds, departmentMemberIds...)
	} else {
		memberIds = []uint64{m.Id}
	}
	m.viewAndOperateMemberIds = memberIds
	return
}

// 初始化拥有的权限key的map
func (m *AdminMember) InitOwnAuthKeyMap(allAuthKeys []string) {
	if m.OwnAuthKeyMap != nil {
		return
	}
	var ownAuthKeys []string
	if m.IsHasAllAuth() {
		ownAuthKeys = allAuthKeys
	} else {
		roleOwnAuths := []string{}
		ownRoles := m.GetOwnRoles()
		for _, role := range ownRoles {
			roleOwnAuths = append(roleOwnAuths, role.Auths...)
		}
		ownAuthKeys = util.SliceIntersect(allAuthKeys, roleOwnAuths)
	}
	m.OwnAuthKeyMap = map[string]struct{}{}
	for _, ownAuthKey := range ownAuthKeys {
		m.OwnAuthKeyMap[ownAuthKey] = struct{}{}
	}
}

// 处理拥有的子菜单权限
func (m *AdminMember) handleOwnSubMenuAuth(auth *AdminAuth) {
	if len(auth.SubMenuAuths) <= 0 {
		return
	}
	subMenuAuths := auth.SubMenuAuths
	auth.SubAuths = []*AdminAuth{}
	auth.SubMenuAuths = []*AdminAuth{}
	for _, subMenuAuth := range subMenuAuths {
		if _, exists := m.OwnAuthKeyMap[subMenuAuth.Key]; exists {
			newSubMenuAuth := *subMenuAuth
			m.handleOwnSubMenuAuth(&newSubMenuAuth)
			auth.SubMenuAuths = append(auth.SubMenuAuths, &newSubMenuAuth)
		}
	}
}

// 初始化拥有的权限
func (m *AdminMember) InitOwnAuths(allAuths []*AdminAuth, allAuthKeys []string) {
	if m.OwnAuths != nil {
		return
	}
	auths := []*AdminAuth{}
	m.InitOwnAuthKeyMap(allAuthKeys)
	for _, auth := range allAuths {
		if _, exist := m.OwnAuthKeyMap[auth.Key]; exist {
			newAuth := *auth // 获取指针值赋值给另外的变量
			auths = append(auths, &newAuth)
		}
	}
	m.OwnAuths = auths
}

// 初始化拥有的菜单权限
func (m *AdminMember) InitOwnMenuAuths(allMenuAuths []*AdminAuth, allAuthKeys []string) {
	m.InitOwnAuthKeyMap(allAuthKeys)
	// 初始化拥有的侧边栏菜单权限
	if m.OwnSidebarMenuAuths == nil {
		silebarAuths := []*AdminAuth{}
		m.InitOwnAuthKeyMap(allAuthKeys)
		for _, auth := range allMenuAuths {
			_, exists := m.OwnAuthKeyMap[auth.Key]
			if exists && auth.Type == authenum.TYPE_SIDEBAR_MENU && auth.ParentKey == "" {
				newAuth := *auth // 获取指针值赋值给另外的变量
				// fmt.Printf("3333|%v|%v\r\n", newAuth.Key, newAuth.SubMenuAuths)
				m.handleOwnSubMenuAuth(&newAuth)
				silebarAuths = append(silebarAuths, &newAuth)
			}
		}
		m.OwnSidebarMenuAuths = silebarAuths
	}
	// 初始化拥有的顶部菜单权限
	if m.OwnTopMenuAuths == nil {
		topAuths := []*AdminAuth{}
		m.InitOwnAuthKeyMap(allAuthKeys)
		for _, auth := range allMenuAuths {
			_, exists := m.OwnAuthKeyMap[auth.Key]
			if exists && auth.Type == authenum.TYPE_TOP_MENU && auth.ParentKey == "" {
				newAuth := *auth // 获取指针值赋值给另外的变量
				m.handleOwnSubMenuAuth(&newAuth)
				topAuths = append(topAuths, &newAuth)
			}
		}
		m.OwnTopMenuAuths = topAuths
	}
}
